// Final cache verification test
const path = require('path');
const fs = require('fs-extra');

// Real BriefingService with debug logging
class RealBriefingServiceDebug {
  constructor() {
    const { Ollama } = require('ollama');
    this.ollama = new Ollama({
      host: 'http://localhost:11434',
    });
    this.briefingsPath = path.join(process.cwd(), '.cb-document-helper', 'briefings');
    this.ollamaCallCount = 0; // Track actual Ollama calls
  }

  async getBriefing(filePath) {
    try {
      const briefingFile = this.getBriefingFilePath(filePath);
      console.log(`🔍 Checking cache for: ${briefingFile}`);
      
      if (await fs.pathExists(briefingFile)) {
        console.log('✅ Cache file exists, checking validity...');
        const briefingData = await fs.readJson(briefingFile);
        
        // 检查文件是否已修改
        const stat = await fs.stat(filePath);
        const cachedModified = new Date(briefingData.fileModified);
        
        console.log(`📅 File mtime: ${stat.mtime.toISOString()}`);
        console.log(`📅 Cached mtime: ${cachedModified.toISOString()}`);
        
        if (stat.mtime <= cachedModified) {
          console.log('🎯 CACHE HIT - returning cached briefing (no Ollama call)');
          return briefingData.briefing;
        } else {
          console.log('⚠️  File modified since cache - regenerating');
        }
      } else {
        console.log('❌ No cache file found - will generate new briefing');
      }

      // 如果简介不存在或文件已修改，重新生成
      console.log('🤖 Calling Ollama to generate briefing...');
      this.ollamaCallCount++;
      console.log(`📞 Ollama call count: ${this.ollamaCallCount}`);
      
      const content = await fs.readFile(filePath, 'utf-8');
      const matter = require('gray-matter');
      const parsed = matter(content);
      
      const documentInfo = {
        filePath,
        content,
        frontMatter: parsed.data,
        lastModified: (await fs.stat(filePath)).mtime,
      };

      const briefing = await this.generateBriefing(documentInfo);
      return briefing;
    } catch (error) {
      console.error(`❌ Error getting briefing for ${filePath}:`, error);
      return `Error loading briefing for ${filePath}: ${error}`;
    }
  }

  async generateBriefing(documentInfo) {
    try {
      await fs.ensureDir(this.briefingsPath);

      const prompt = this.createSummaryPrompt(documentInfo);
      
      const response = await this.ollama.generate({
        model: 'qwen3:14b',
        prompt,
        options: {
          temperature: 0.3,
          top_p: 0.9,
          top_k: 40,
        },
      });

      let briefing = response.response.trim();
      
      // 清理模型输出中的思考过程标签
      briefing = this.cleanBriefingResponse(briefing);
      
      // 确保简介不超过600字
      const truncatedBriefing = this.truncateToBriefing(briefing);
      
      // 保存到磁盘
      await this.saveBriefing(documentInfo.filePath, truncatedBriefing, documentInfo.lastModified);
      
      return truncatedBriefing;
    } catch (error) {
      console.error(`Error generating briefing for ${documentInfo.filePath}:`, error);
      throw error;
    }
  }

  createSummaryPrompt(documentInfo) {
    const frontMatterInfo = Object.keys(documentInfo.frontMatter).length > 0 
      ? `\n\nFrontmatter metadata:\n${JSON.stringify(documentInfo.frontMatter, null, 2)}`
      : '';

    return `请为以下markdown文档写一个简洁的中文摘要，要求：
1. 摘要长度不超过500字
2. 突出文档的主要内容和关键信息
3. 关注文档的内容，而非结构。比如，如果此文档描述了一个角色，你应摘要：<角色名>，男，性格<性格>，是一个<角色描述>，而不是：此文档包含角色性别、性格、描述方面的信息
4. 如果有frontmatter元数据，请在摘要中提及相关信息
5. 直接输出摘要内容，不要包含思考过程或其他标签

文档路径: ${documentInfo.filePath}${frontMatterInfo}

文档内容:
${documentInfo.content}

请生成摘要:`;
  }

  cleanBriefingResponse(text) {
    let cleaned = text;
    cleaned = cleaned.replace(/<think>[\s\S]*?<\/think>/g, '');
    cleaned = cleaned.replace(/<\/?[a-zA-Z][^>]*>/g, '');
    cleaned = cleaned.replace(/\n\s*\n/g, '\n').trim();
    return cleaned;
  }

  truncateToBriefing(text) {
    if (text.length <= 600) {
      return text;
    }

    const sentences = text.split(/[。！？.!?]/);
    let result = '';
    
    for (const sentence of sentences) {
      if ((result + sentence).length > 580) {
        break;
      }
      result += sentence + (sentence.trim() ? '。' : '');
    }

    if (result.length < 100) {
      result = text.substring(0, 597) + '...';
    }

    return result.trim();
  }

  async saveBriefing(filePath, briefing, fileModified) {
    const briefingFile = this.getBriefingFilePath(filePath);
    
    const briefingData = {
      filePath,
      briefing,
      lastUpdated: new Date(),
      fileModified: fileModified,
    };

    console.log(`💾 Saving briefing to cache: ${briefingFile}`);
    await fs.writeJson(briefingFile, briefingData, { spaces: 2 });
  }

  getBriefingFilePath(filePath) {
    const hash = this.hashString(filePath);
    return path.join(this.briefingsPath, `${hash}.json`);
  }

  hashString(str) {
    let hash = 0;
    for (let i = 0; i < str.length; i++) {
      const char = str.charCodeAt(i);
      hash = ((hash << 5) - hash) + char;
      hash = hash & hash;
    }
    return Math.abs(hash).toString(36);
  }

  async clearBriefings() {
    try {
      if (await fs.pathExists(this.briefingsPath)) {
        await fs.emptyDir(this.briefingsPath);
      }
    } catch (error) {
      console.error('Error clearing briefings:', error);
    }
  }
}

async function finalCacheVerification() {
  console.log('🎯 Final Cache Verification Test\n');
  
  const briefingService = new RealBriefingServiceDebug();
  
  // Create test file
  const testFile = './final-cache-test.md';
  const testContent = `---
title: "最终缓存验证"
author: "测试团队"
---

# 最终缓存验证测试

这是用于最终验证缓存机制的测试文档。

## 测试目标
- 验证缓存确实避免了重复的Ollama调用
- 验证缓存命中时性能提升显著
- 验证缓存失效机制正常工作
`;

  try {
    // Clear cache first
    await briefingService.clearBriefings();
    console.log('🧹 Cleared existing cache\n');
    
    // Write test file
    await fs.writeFile(testFile, testContent);
    console.log('📄 Created test file\n');
    
    // === Test 1: First call (should call Ollama) ===
    console.log('=== TEST 1: First Call (Should Generate New) ===');
    const start1 = Date.now();
    const briefing1 = await briefingService.getBriefing(testFile);
    const time1 = Date.now() - start1;
    console.log(`⏱️  Time: ${time1}ms`);
    console.log(`📊 Ollama calls so far: ${briefingService.ollamaCallCount}`);
    console.log(`📝 Briefing preview: ${briefing1.substring(0, 80)}...\n`);
    
    // === Test 2: Immediate second call (should use cache) ===
    console.log('=== TEST 2: Second Call (Should Use Cache) ===');
    const start2 = Date.now();
    const briefing2 = await briefingService.getBriefing(testFile);
    const time2 = Date.now() - start2;
    console.log(`⏱️  Time: ${time2}ms`);
    console.log(`📊 Ollama calls so far: ${briefingService.ollamaCallCount}`);
    console.log(`📝 Briefing preview: ${briefing2.substring(0, 80)}...\n`);
    
    // === Verification ===
    console.log('=== VERIFICATION ===');
    console.log(`Content identical: ${briefing1 === briefing2}`);
    console.log(`Speed improvement: ${(time1 / Math.max(time2, 1)).toFixed(2)}x`);
    console.log(`Ollama call savings: ${briefingService.ollamaCallCount === 1 ? 'YES (only 1 call)' : 'NO (multiple calls)'}\n`);
    
    if (briefing1 === briefing2 && briefingService.ollamaCallCount === 1) {
      console.log('✅ CACHE IS WORKING PERFECTLY!');
    } else {
      console.log('❌ Cache issue detected');
    }
    
    // === Test 3: Cache invalidation ===
    console.log('\n=== TEST 3: Cache Invalidation ===');
    await new Promise(resolve => setTimeout(resolve, 1000)); // Wait to ensure different mtime
    await fs.writeFile(testFile, testContent + '\n\n## 新增内容\n修改文件以测试缓存失效。');
    console.log('📝 Modified file content');
    
    const start3 = Date.now();
    const briefing3 = await briefingService.getBriefing(testFile);
    const time3 = Date.now() - start3;
    console.log(`⏱️  Time: ${time3}ms`);
    console.log(`📊 Ollama calls so far: ${briefingService.ollamaCallCount}`);
    console.log(`📝 Briefing preview: ${briefing3.substring(0, 80)}...\n`);
    
    console.log('=== INVALIDATION VERIFICATION ===');
    console.log(`Content changed: ${briefing3 !== briefing1}`);
    console.log(`New Ollama call made: ${briefingService.ollamaCallCount === 2 ? 'YES' : 'NO'}\n`);
    
    if (briefing3 !== briefing1 && briefingService.ollamaCallCount === 2) {
      console.log('✅ CACHE INVALIDATION WORKS PERFECTLY!');
    } else {
      console.log('❌ Cache invalidation issue detected');
    }
    
    // === Final Summary ===
    console.log('\n=== FINAL SUMMARY ===');
    console.log(`Total Ollama calls: ${briefingService.ollamaCallCount}`);
    console.log(`Expected calls: 2 (1 initial + 1 after modification)`);
    console.log(`Cache efficiency: ${briefingService.ollamaCallCount === 2 ? 'OPTIMAL' : 'NEEDS IMPROVEMENT'}`);
    
    // Cleanup
    await fs.remove(testFile);
    console.log('\n🧹 Cleaned up test file');
    
  } catch (error) {
    console.error('💥 Final verification failed:', error);
    try {
      await fs.remove(testFile);
    } catch (cleanupError) {
      // Ignore cleanup errors
    }
  }
}

// Run final verification
finalCacheVerification().catch(error => {
  console.error('💥 Final verification runner failed:', error);
  process.exit(1);
});
